package batframework.mvc;

import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import batframework.code.util.ClassUtils;
import batframework.mvc.render.JsonRender;
import batframework.mvc.render.RedirectRender;
import batframework.mvc.render.ViewRender;


public abstract class Controller
{
	private HttpServletRequest request;
	
	private HttpServletResponse response;

	private HttpSession session;
	
	private Render render;
	
	public Param param;
	
	public ModelMap model;
		
	/**
	 * this method is system call
	 * don't use it
	 * @author yue
	 */
	public final void init(HttpServletRequest request,HttpServletResponse response,Render render)
	{
		this.request = request;
		this.response = response;
		this.session = this.request.getSession();
		this.setRender(render);
		this.param = new Param(this.request);
		this.model = new ModelMap();
	}
	
	/**
	 * 
	 * @author bmyues
	 * @return
	 */
	public final HttpServletRequest getRequest()
	{
		return request;
	}

	/**
	 * 
	 * @author bmyues
	 * @return
	 */
	public final HttpServletResponse getResponse()
	{
		return response;
	}

	/**
	 * 
	 * @author bmyues
	 * @return
	 */
	public final HttpSession getSession()
	{
		return session;
	}
	
	/**
	 * 
	 * @author bmyues
	 */
	public final void render()
	{
		
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param name
	 * @param value
	 * @return
	 */
	public final Controller addAttr(String name,Object value)
	{
		model.addAttr(name, value);
		return this;
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param attrs
	 * @return
	 */
	public final Controller addAttrs(Map<String,Object> attrs)
	{
		model.addAttrs(attrs);
		return this;
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param name
	 * @return
	 */
	public final Cookie getCookie(String name)
	{
		Cookie[] cookies = request.getCookies();
		for (Cookie cookie : cookies)
			if(cookie.getName().equals(name))
				return cookie;
		return null;
	}
	
	//cookie cache
	private Cookie cookie;
	
	/**
	 * 
	 * @author bmyues
	 * @param name
	 * @return
	 */
	public final String getCookieValue(String name)
	{
		if(cookie == null)
		   this.cookie = getCookie(name);
		if(cookie != null)
			cookie.getValue();
		return null;
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param name
	 * @return
	 */
	public final String getParam(String name)
	{
		return param.getParam(name);
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param view
	 */
	public final void render(String view)
	{
		this.setRender(new ViewRender(view));
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param view
	 */
	public final void render(View view)
	{
		this.setRender(new ViewRender(view));
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param render
	 */
	public final void render(Render render)
	{
		this.setRender(render);
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param view
	 */
	public final void viewRender(String view)
	{
		render(view);
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param view
	 */
	public final void viewRender(View view)
	{
		render(view);
	}
	
	/**
	 * 
	 * @author bmyues
	 */
	public final void jsonRender()
	{
		this.setRender(new JsonRender(model.getAttrs()));
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param data
	 */
	public final void jsonRender(Object data)
	{
		this.setRender(new JsonRender(data));
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param json
	 */
	public final void jsonRender(String json)
	{
		this.setRender(new JsonRender(json));
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param url
	 */
	public final void redirect(String url)
	{
		this.setRender(new RedirectRender(url));
	}
	
	/**
	 * 
	 * @author bmyues
	 */
	public final void destroy()
	{
		
	}
	
	/**
	 * 
	 * @author bmyues
	 * @param module
	 * @return
	 */
	public final <M> M module(Class<?> module)
	{
		return ClassUtils.createObject(module);
	}
	
	@SuppressWarnings("unchecked")
	public final <M> M module(Object module)
	{
		return (M) module;
	}

	public Render getRender()
	{
		return render;
	}

	public void setRender(Render render)
	{
		this.render = render;
	}
}
